//
//  CKWeakSet.m
//  ChatKit
//
//  Created by Ofri Wolfus on 25/03/06.
//  Copyright 2006 Ofri Wolfus. All rights reserved.
//

#import "CKWeakSet.h"


//Let the compiler know about NSCFSet
@interface NSCFSet : NSMutableSet {
}
@end

//CKCFWeakSet inherits from NSCFSet so that we wont have to rewrite apple's implementation.
//CKCFWeakSet only creates a CFMutableSetRef with no retain/release callbacks, and lets apple's implementation deal with the rest.
//This all works because NSCFSet is toll free bridged to CFSet and CFMutableSet.
@interface CKCFWeakSet : NSCFSet {
}
@end

//CKCFWeakSet is the real implementation of CKWeakSet.
//CKWeakSet itself is just a class that does nothing.
@implementation CKCFWeakSet

//Create a CFMutableSet with no retain/release callbacks
- (id)initWithCapacity:(unsigned)numItems {
	/* Because NSCFSet is toll free bridged to CFSet, we inherit its "bridge" as well.
	 * CoreFoundation and the ObjC runtime can tell when an object is a "native" ObjC object, or a CFType.
	 * In our case, NSCFSet is assumed to be CFSet and therefor, when we get sent a release message, CFRelease() will get called.
	 * This makes it impossible for us to release the space allocated in +alloc with a simple -release, and therefor we deallocate it directly.
	 */
	NSDeallocateObject(self);
	
	//Return a simple CFMutableSet
	return (id)CFSetCreateMutable(kCFAllocatorDefault, numItems, NULL);
}

//For some reason we have to override this as well.
//It seems that NS(Mutable)Set implements it directly instead of calling -initWithCapacity:
- (id)init {
	return [self initWithCapacity:0];
}

@end


//CKWeakSet is a transparent class which is meant to just hide the details from the user.
//When an attempt to allocate a new CKWeakSet is made, we'll just allocate new CKCFWeakSet instead and return that.
@implementation CKWeakSet

+ (id)set {
	return [[[CKCFWeakSet alloc] init] autorelease];
}

+ (id)allocWithZone:(NSZone *)zone {
	return [CKCFWeakSet allocWithZone:zone];
}

//We're not supposed to get here anyway, but what the hell...
- (id)init {
	[self release];
	return [[CKCFWeakSet alloc] init];
}

- (id)initWithCapacity:(unsigned)numItems {
	[self release];
	return [[CKCFWeakSet alloc] initWithCapacity:numItems];
}

@end


//Add support for weak sets from NSMutableSet
@implementation NSMutableSet (CKWeakSet)

+ (id)weakSetWithCapacity:(unsigned)numItems {
	return [[[CKWeakSet alloc] initWithCapacity:numItems] autorelease];
}

@end
